package com.su.kddq.security.filter;

import com.su.kddq.security.security.TokenManager;
import com.su.kddq.utils.result.R;
import com.su.kddq.utils.result.ResponseUtil;
import com.su.kddq.utils.result.ResultCode;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.StringUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;

/**
 * <p>
 * 访问过滤器
 * </p>
 *
 * @author sx
 */
public class TokenAuthenticationFilter extends BasicAuthenticationFilter {

    private TokenManager tokenManager;
    private RedisTemplate redisTemplate;

    public TokenAuthenticationFilter(AuthenticationManager authManager, TokenManager tokenManager, RedisTemplate redisTemplate) {
        super(authManager);
        this.tokenManager = tokenManager;
        this.redisTemplate = redisTemplate;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
            throws IOException, ServletException {

        logger.info("=================" + req.getRequestURI());

        String checkToken="null";
        String token = req.getHeader("token");

        if (StringUtils.isEmpty(token)||checkToken.equals(token)) {
            ResponseUtil.out(res, R.error().code(ResultCode.NO_AUTHORIZATION));
            return;
        }

        UsernamePasswordAuthenticationToken authentication;
        try {
            authentication = getAuthentication(req);
        } catch (NullPointerException e) {
            ResponseUtil.out(res, R.error().code(ResultCode.TOKEN_FAIL));
            return;
        }

        if (authentication != null) {
            SecurityContextHolder.getContext().setAuthentication(authentication);
        } else {
            logger.error("token过期");
            ResponseUtil.out(res, R.error().code(ResultCode.TOKEN_EXPIRED));
            return;
        }
        chain.doFilter(req, res);
    }

    private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
        // token置于header里
        String token = request.getHeader("token");
        String userName = tokenManager.getUserFromToken(token);
        if (StringUtils.isEmpty(userName)) {
            return null;
        }
        Integer permissionValue = (Integer) redisTemplate.opsForValue().get(userName);
        Collection<GrantedAuthority> authorities = new ArrayList<>();
        if (StringUtils.isEmpty(permissionValue)) {
            return null;
        }
        SimpleGrantedAuthority authority = new SimpleGrantedAuthority(String.valueOf(permissionValue));
        authorities.add(authority);
        return new UsernamePasswordAuthenticationToken(userName, token, authorities);
    }

}